#include "GameEnemy.h"

GameEnemy::GameEnemy()
{
	m_moveSpd = 0.0f;
	m_viewW = 0.0f;
	m_viewR = 0.0f;

	m_targetFound = false;
	m_target = 0;

	
	m_wandering = true;

	m_currentPathIndex = 0;

	
	path = new TemplateVector<GraphNode<mapNode>*>;
	returningPath = false;

}

GameEnemy::~GameEnemy(){
	path->release();
	delete path;
}

void GameEnemy::initEnemy(float a_moveSpd, float a_vWid, float a_vRad)
{
	m_moveSpd = a_moveSpd;
	m_viewW = a_vWid;
	m_viewR = a_vRad;
}

void GameEnemy::initTarget(GameObject* a_target)
{
	m_target = a_target;
}

void GameEnemy::initLine(List<clkObject*>* a_objs)
{
	m_objs = a_objs;
}

bool GameEnemy::enemyUpdate()
{
	m_view = genTriCone(m_body->m_pos,m_body->m_look,m_viewW,m_viewR);
	
	//ray tracing view begin
	
	if(path->size())
		nextNode();

	V2DF pntA, pntB;
	clkObject* objA = 0;
	clkObject* objB = 0;
	float disA = m_view.m_vert[0].distance(m_view.m_vert[1]);
	float disB = m_view.m_vert[0].distance(m_view.m_vert[2]);

	m_lineA[0] = m_view.m_vert[0];
	m_lineA[1] = m_view.m_vert[0];
	m_lineB[0] = m_view.m_vert[0];
	m_lineB[1] = m_view.m_vert[0];

	int size = m_objs->size();
	for(int i = 0; i < size; i++)
	{
		clkObject* obj = m_objs->get(i);

		if(obj == m_body)
			continue;

		if(obj == m_target->m_body)
			continue;

		if(!obj->m_isCollidable)
			continue;

		for(int j = 0; j < 4; j++)
		{
			if(intersectL2L(m_view.m_vert[0],m_view.m_vert[1],
				obj->m_vertR[idx[j].x],obj->m_vertR[idx[j].y],&pntA))
			{
				float d = m_view.m_vert[0].distance(pntA);
				if(d < disA)
				{
					disA = d;
					m_lineA[0] = obj->m_vertR[idx[j].x];
					m_lineA[1] = obj->m_vertR[idx[j].y];
					m_view.m_vert[1] = pntA;
					objA = obj;
				}
			}
			if(intersectL2L(m_view.m_vert[0],m_view.m_vert[2],
				obj->m_vertR[idx[j].x],obj->m_vertR[idx[j].y],&pntB))
			{
				float d = m_view.m_vert[0].distance(pntB);
				if(d < disB)
				{
					disB = d;
					m_lineB[0] = obj->m_vertR[idx[j].x];
					m_lineB[1] = obj->m_vertR[idx[j].y];
					m_view.m_vert[2] = pntB;
					objB = obj;
				}
			}
		}

		if(objA == objB && objA != 0 && objB != 0)
		{
			m_lineA[1] = m_view.m_vert[2];
			m_lineB[0] = m_view.m_vert[1];
		}
	}

	//ray tracing view end

	V2DF vert[7];
	vert[0] = m_view.m_vert[0];
	vert[1] = m_view.m_vert[1];
	vert[2] = m_view.m_vert[2];
	vert[3] = m_lineA[0];
	vert[4] = m_lineA[1];
	vert[5] = m_lineB[0];
	vert[6] = m_lineB[1];

	V2DF norm[7];
	norm[0] = m_view.m_vert[0].perp().normal();
	norm[1] = m_view.m_vert[1].perp().normal();
	norm[2] = m_view.m_vert[2].perp().normal();
	norm[3] = m_lineA[0].perp().normal();
	norm[4] = m_lineA[1].perp().normal();
	norm[5] = m_lineB[0].perp().normal();
	norm[6] = m_lineB[1].perp().normal();

	if(m_target)
	{
		if(satCollision(
			m_target->m_body->m_vertR,
			m_target->m_body->m_vertRN,4,
			vert,
			norm,7))
		{
			m_targetFound = true;
		}
		else
			m_targetFound = false;
	}

	if(path->size())
		seek();

	m_body->m_rot = DEGREE(polarAngle(GameBody::m_body->m_lnVel.normal()));

	aniPlay();
	GameTexture::m_pos = GameBody::m_body->m_pos;
	GameTexture::m_rot = GameBody::m_body->m_rot;
	GameTexture::update();
	if(m_targetFound)
		return true;
	return false;
}

void GameEnemy::draw()
{
	drawTri(m_core,m_view.m_vert,(m_targetFound)?CL_RED:CL_GREEN);
	m_core->drawLine(m_view.m_vert[1],m_lineA[1],(m_targetFound)?CL_RED:CL_GREEN);
	m_core->drawLine(m_view.m_vert[2],m_lineB[0],(m_targetFound)?CL_RED:CL_GREEN);
	//drawPath();
	GameTexture::draw();
}

void GameEnemy::drawPath()
{
	if(path)
	{
		int length = path->size();
		for (int i = 0; i < length-1; i++)
		{
			V2DF start = V2DF((float)path->get(i)->value.pos.x*64,(float)path->get(i)->value.pos.y*64);
			V2DF end = V2DF((float)path->get(i+1)->value.pos.x*64,(float)path->get(i+1)->value.pos.y*64);
			m_core->drawLine(start,end,CL_RED);
		}
	}
}

void GameEnemy::seek()
{
	V2DF xy = V2DF((float)path->get(m_currentPathIndex)->value.pos.x*64,
		(float)path->get(m_currentPathIndex)->value.pos.y*64);
	seekPos(xy);
}

void GameEnemy::seekPos(Vector2D<float> a_pos)
{
	Vector2D<float> tempPos = a_pos - getPos();
	m_body->m_lnFrc += tempPos.normal() * m_moveSpd * 0.2f;

	//needs to include snapping view to movement direction.
	// rotation = direction
}

bool GameEnemy::onNode(Vector2D<float> a_pos)//checks to see if the entity is close enough to the center of a node (assuming a_pos is the center of the node)
{
	float ax = getPos().x - a_pos.x;
	float ay = getPos().y - a_pos.y;

	if(m_body->m_pos.distance(a_pos) < 20 ) //using 20 as a "close enough" area to start heading towards the next node, replace with non-magic number later.
		return true;
	else
		return false;
} 

void GameEnemy::nextNode()
{
	V2DF xy = V2DF(m_body->m_pos.x/64.0f, m_body->m_pos.y/64.0f);
	V2DI node = path->get(m_currentPathIndex)->value.pos; 
	if (((xy.x < node.x+1.0f)&&(xy.x > node.x-1.0f)&&
		(xy.y < node.y+1.0f)&&(xy.y > node.y-1.0f)))
	{
		if(!returningPath)
		{
			if (m_currentPathIndex < path->size()-1)
			{
				m_currentPathIndex++;
			}
			else
			{
				m_currentPathIndex = path->size()-2;
				returningPath = true;
			}
		}
		else
		{
			if (m_currentPathIndex > 0)
			{
				m_currentPathIndex--;
			}
			else
			{
				m_currentPathIndex = 1;
				returningPath = false;
			}
		}
	}
}